﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using KeePassLib;
using System.Collections;
using KeePass.UI;
using System.Linq;

namespace KeePass.Forms
{
    public partial class AddAlternativeUsers : Form
    {
        private PwDatabase db;
        private List<AlternativeUser> altUsers;
        private List<AlternativeUser> filteredList;
        private CustomTreeViewEx ctmMainForm;
        private AlternativeUser selectedUser;

        public AddAlternativeUsers(PwDatabase db, CustomTreeViewEx ctmMainForm)
        {
            this.db = db;
            this.ctmMainForm = ctmMainForm;
            InitializeComponent();
            ActivateEvents();
            altUsers = db.AlternativeUsers;
            filteredList = new List<AlternativeUser>();
            FillUsers(altUsers);
        }

        private void ActivateEvents()
        {
            dataGridViewUsers.RowValidating += new DataGridViewCellCancelEventHandler(dataGridViewUsers_RowValidating);
            dataGridViewUsers.PreviewKeyDown += new PreviewKeyDownEventHandler(dataGridViewUsers_PreviewKeyDown);
            dataGridViewUsers.UserDeletingRow += new DataGridViewRowCancelEventHandler(dataGridViewUsers_UserDeletingRow);
            dataGridViewUsers.CellFormatting += new DataGridViewCellFormattingEventHandler(dataGridViewUsers_CellFormatting);
            dataGridViewUsers.CellEnter += new DataGridViewCellEventHandler(dataGridViewUsers_CellEnter);
            dataGridViewUsers.RowEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridViewUsers_RowEnter);
            dataGridViewUsers.SelectionChanged += new EventHandler(dataGridViewUsers_SelectionChanged);
            dataGridViewUsers.KeyDown += new KeyEventHandler(dataGridViewUsers_KeyDown);
        }

        private void dataGridViewUsers_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete && dataGridViewUsers.SelectedRows.Count >= 1 && dataGridViewUsers.SelectedRows[dataGridViewUsers.SelectedRows.Count-1] != dataGridViewUsers.Rows[dataGridViewUsers.Rows.Count - 1])
                e.Handled = !ConfirmDelete(); 
        }

        private void dataGridViewUsers_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (e.ColumnIndex == 1 && e.Value != null)
            {
                dataGridViewUsers.Rows[e.RowIndex].Tag = e.Value;
                e.Value = new String('●', e.Value.ToString().Length);
            }
        }

        private void dataGridViewUsers_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            dataGridViewUsers.SelectionChanged -= dataGridViewUsers_SelectionChanged;
            ucEditReadList.Remove(ucEditReadList.Find(kvp =>kvp.Key.Equals(selectedUser)));
            ucEditWriteList.Remove(ucEditWriteList.Find(kvp =>kvp.Key.Equals(selectedUser)));
            DeleteRow();
            SetSelectedUser();
            dataGridViewUsers.SelectionChanged += dataGridViewUsers_SelectionChanged;
        }

        private void DeleteUserFromListsRecursive(PwGroup group)
        {
            group.RemoveReadableUser(selectedUser);
            group.RemoveWritableUser(selectedUser);

            foreach (PwGroup subGr in group.Groups)
                DeleteUserFromListsRecursive(subGr);
        }

        private void DeleteRow()
        {
            try
            {
                DeleteUserFromListsRecursive(db.RootGroup);
                altUsers.Remove(selectedUser);
            }
            catch (Exception exeption)
            {
                MessageBox.Show("Couldn't remove user: " + exeption);
            }
        }

        private void FillUsers(List<AlternativeUser> userList)
        {
            foreach (AlternativeUser u in userList)
                dataGridViewUsers.Rows.Add(u.Username, u.Password);
            
            if (userList.Count == 0)
            {
                selectedUser = null;
                AddReadWritePanels();
            }
        }

        private bool ConfirmDelete()
        {
            return (MessageBox.Show("Are you sure you want to permanently delete this user(s)?", "Confirm delete", MessageBoxButtons.OKCancel) == DialogResult.OK);   
        }

        private void dataGridViewUsers_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                if (dataGridViewUsers.IsCurrentCellDirty)
                    dataGridViewUsers.CancelEdit();

                else if (dataGridViewUsers.IsCurrentRowDirty)
                {
                    if (ConfirmDelete())
                    {
                        DeleteRow();
                        dataGridViewUsers.Rows.Remove(dataGridViewUsers.CurrentRow);
                    }
                }
            }
        }

        private bool ValidateRow(int rowIndex)
        {            
            DataGridViewRow dgvr = dataGridViewUsers.Rows[rowIndex];           

            if (dgvr.Cells["UserName"].Value == null || dgvr.Cells["Password"].Value == null)
                if (!dataGridViewUsers.CurrentRow.IsNewRow)
                {
                    MessageBox.Show("Enter valid values in all fields of the row.");
                    return false;
                }
            if (dgvr.Cells[0].Value != null && dgvr.Cells[1].Value != null)
            {
                if (dgvr.Cells["UserName"].Value.ToString() != "" || dgvr.Cells["Password"].Value.ToString() != "")
                {
                    if (dgvr.Cells["Password"].Value.ToString() == "")
                    {
                        if (dataGridViewUsers.CurrentRow.Tag != null)
                            dgvr.Cells["Password"].Value = dgvr.Tag;
                    }

                    AlternativeUser newUser = new AlternativeUser(dgvr.Cells["UserName"].Value.ToString(), dgvr.Cells["Password"].Value.ToString());

                    if (altUsers.Count == rowIndex)
                        altUsers.Add(newUser);
                    else
                    {
                        int i = altUsers.FindIndex(user => user.Username.Equals(selectedUser.Username));
                        altUsers[i].Username = newUser.Username;
                        altUsers[i].Password = newUser.Password;
                    }
                }
                if (!CheckIfUsernameIsUnique(dgvr))
                {
                    MessageBox.Show("Username has to be unique.");
                    return false;
                }
            }

            SetSelectedUser();
            return true;
        }

        private void dataGridViewUsers_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
        {
            if (dataGridViewUsers.IsCurrentRowDirty )         
                e.Cancel = !ValidateRow(e.RowIndex);
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
          /*  try
            {
                db.AlternativeUsers = new List<AlternativeUser>(altUsers);
                this.DialogResult = DialogResult.OK;
                MessageBox.Show("All users succesfully saved!");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }*/
            this.Close();
        }

        private bool CheckIfUsernameIsUnique(DataGridViewRow dgvr)
        {
            int counter = 0;

            if (dgvr.Cells[0].Value != null)
            {
                List<AlternativeUser> altUsersCopy = new List<AlternativeUser>(altUsers);
                foreach (AlternativeUser user in altUsersCopy)
                {
                    if (user.Username == dgvr.Cells[0].Value.ToString())
                    {
                        if (counter >= 1)
                            altUsers.Remove(user);
                        counter++;
                    }
                }
            }    
            return (counter <= 1);
        }

        private List<KeyValuePair<AlternativeUser,UserControlEditReadRights>> ucEditReadList=new List<KeyValuePair<AlternativeUser,UserControlEditReadRights>>();
        private List<KeyValuePair<AlternativeUser,UserControlEditWriteRights>> ucEditWriteList=new List<KeyValuePair<AlternativeUser,UserControlEditWriteRights>>();
        private UserControlEditReadRights activeUCEditRead;
        private UserControlEditWriteRights activeUCEditWrite;

        private void AddReadWritePanels()
        {
            this.pnlRead.Controls.Clear();
            this.pnlWrite.Controls.Clear();

            if (selectedUser != null)
            {
                KeyValuePair<AlternativeUser, UserControlEditReadRights>? kvpRead = ucEditReadList.FirstOrDefault(readkvp => readkvp.Key.Equals(selectedUser));
                KeyValuePair<AlternativeUser, UserControlEditWriteRights>? kvpWrite = ucEditWriteList.FirstOrDefault(writekvp => writekvp.Key.Equals(selectedUser));
                if (kvpRead.Value.Value != null)
                    activeUCEditRead = kvpRead.Value.Value;
                else
                {
                    activeUCEditRead = new UserControlEditReadRights(selectedUser, db, ctmMainForm);
                    ucEditReadList.Add(new KeyValuePair<AlternativeUser, UserControlEditReadRights>(selectedUser, activeUCEditRead));
                }
                if (kvpWrite.Value.Value != null)
                    activeUCEditWrite = kvpWrite.Value.Value;
                else
                {
                    activeUCEditWrite = new UserControlEditWriteRights(selectedUser, db, ctmMainForm);
                    ucEditWriteList.Add(new KeyValuePair<AlternativeUser, UserControlEditWriteRights>(selectedUser, activeUCEditWrite));
                }
            }
            else
            {
                activeUCEditRead = new UserControlEditReadRights(selectedUser, db, ctmMainForm);
                activeUCEditWrite = new UserControlEditWriteRights(selectedUser, db, ctmMainForm);
            }

            this.pnlRead.Controls.Add(activeUCEditRead);
            this.pnlWrite.Controls.Add(activeUCEditWrite);
        }

        private void textBoxSearch_TextChanged(object sender, EventArgs e)
        {
            dataGridViewUsers.AllowUserToAddRows = textBoxSearch.Text.Length == 0;
            dataGridViewUsers.RowValidating -= dataGridViewUsers_RowValidating;

            dataGridViewUsers.Rows.Clear();
            filteredList.Clear();
            if (textBoxSearch.Text.Length > 0)
            {
                foreach (AlternativeUser u in altUsers)
                {
                    if (u.Username.ToLower().Contains(textBoxSearch.Text.ToLower()))
                        filteredList.Add(u);
                }
                FillUsers(filteredList);
            }
            else 
                FillUsers(altUsers);

            ((TextBox)sender).Focus();
            dataGridViewUsers.RowValidating += dataGridViewUsers_RowValidating;
        }

        private void dataGridViewUsers_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
            rowChanged = true;
        }

        private bool rowChanged = false;

        private void dataGridViewUsers_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            if(rowChanged)
                SetSelectedUser();
        }

        private void dataGridViewUsers_SelectionChanged(object sender, EventArgs e)
        {          
            if(rowChanged)
                SetSelectedUser();
        }

        private bool OneRowSelected()
        {
            bool oneRowSelected = true;
            int i = 0;
            while (oneRowSelected && i < dataGridViewUsers.SelectedCells.Count - 1)
            {
                if (dataGridViewUsers.SelectedCells[i].RowIndex != dataGridViewUsers.SelectedCells[i + 1].RowIndex)
                    oneRowSelected = false;
                i++;
            }

            return oneRowSelected;
        }

        private void SetSelectedUser()
        {
            rowChanged = false;
            if (!OneRowSelected())
                selectedUser = null;

            else
            {
                DataGridViewRow dgvr = dataGridViewUsers.CurrentRow;
                if (dgvr.Cells[0].Value != null && dgvr.Cells[1].Value != null)
                {
                    if (dgvr.Cells["UserName"].Value.ToString() != "" || dgvr.Cells["Password"].Value.ToString() != "")
                    {
                        string username = dgvr.Cells["UserName"].Value.ToString();
                        selectedUser = altUsers.Find(u => u.Username.Equals(username)); 
                    }
                }
                else
                    selectedUser = null;
            }
            
            AddReadWritePanels();
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            textBoxSearch.Clear();
        }
    }
}
